package com.yuneec.fly.fragments;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Color;
import android.net.NetworkInfo;
import android.net.wifi.ScanResult;
import android.net.wifi.SupplicantState;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.yuneec.fly.GlobalParams;
import com.yuneec.fly.R;
import com.yuneec.fly.dialogs.BaseDialogFragment;
import com.yuneec.fly.dialogs.LoginWifiDialog;
import com.yuneec.fly.dialogs.ProgressDialog;
import com.yuneec.fly.utils.BindWifiManage;
import com.yuneec.fly.utils.DialogHelper;
import com.yuneec.fly.utils.WifiHelper;
import com.yuneec.fly.utils.inject.WifiPasswordsSaver;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * Created by jw.gu on 2016/7/15.
 */
public class WifiFragment extends BaseFragment {
    private ArrayList<ScanResult> wifiResultList = new ArrayList<ScanResult>();
    private ListView wifiLV;
    private WifiArrayAdapter wifiAdapter;
    private ScanResult currentSelectedWifi;
    private HashMap<String, WifiPasswordsSaver.WifiPassword> passwords;
    private String connectedSSID;
    private boolean connecting;
    private BindWifiManage bwm;
    private TextView connectedWifiTV;
    private TextView statusTV;
    private ProgressDialog loginProgressDialog;
    private WifiManager wifiManager;
    private List<WifiPasswordsSaver.WifiPassword> wifiPasswords = new ArrayList<WifiPasswordsSaver.WifiPassword>();
    private IntentFilter mIntentFilter = new IntentFilter();
    private boolean showCamera;
    private boolean unregistered = true;
    private Context context;

    @Override
    protected int getContentViewResourceId() {
        return R.layout.fragment_wifi;
    }

    @Override
    public void init(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        context = getActivity();
        showCamera = false;
        connectedWifiTV = (TextView) selfView.findViewById(R.id.connectedWifiTV);
        statusTV = (TextView) selfView.findViewById(R.id.statusTV);
        passwords = new HashMap<String, WifiPasswordsSaver.WifiPassword>();
        wifiResultList = new ArrayList<ScanResult>();
        wifiLV = (ListView) selfView.findViewById(R.id.wifiLV);
        setEmptyView();

        wifiAdapter = new WifiArrayAdapter();
        wifiLV.setAdapter(wifiAdapter);
        wifiLV.setOnItemClickListener(new AdapterView.OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                currentSelectedWifi = wifiResultList.get(position);
                for (final WifiPasswordsSaver.WifiPassword wifiPassword : wifiPasswords) {
                    if (wifiPassword.ssid.equals(wifiResultList.get(position).SSID)) {
                        showLoginProgressDialog();
                        new Thread(new Runnable() {
                            @Override
                            public void run() {
//                                GlobalParams.needReconnectCamera=true;
                                connectWifi(wifiPassword.ssid, wifiPassword.ssid, wifiPassword.cipherType);
                            }
                        }).start();
                        return;
                    }
                }
                showPasswordDialog();
            }
        });
        statusTV.setText(R.string.not_connected);
        selfView.findViewById(R.id.refreshBtn).setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                scanWifi();
            }
        });
        wifiPasswords = WifiPasswordsSaver.getWifiPasswords(context);
        mIntentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
        mIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
        mIntentFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
        mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
        if (unregistered) {
            context.registerReceiver(receiverWifi, mIntentFilter);
        }
        initWifi();
        selfView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
    }

    private void setEmptyView() {
        RelativeLayout emptyView = new RelativeLayout(context);
        ProgressBar loading = new ProgressBar(context);
        RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(100, 100);
        params.addRule(RelativeLayout.CENTER_IN_PARENT);
        emptyView.addView(loading, params);
        ViewGroup parentView = (ViewGroup) wifiLV.getParent();
        parentView.addView(emptyView, 6, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 350));
        wifiLV.setEmptyView(emptyView);
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        try {
            context.unregisterReceiver(receiverWifi);
            unregistered = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (loginProgressDialog != null) {
            loginProgressDialog.dismiss();
        }
    }

    private void saveWifiPassword(WifiPasswordsSaver.WifiPassword pass) throws Exception {
        for (WifiPasswordsSaver.WifiPassword wifiPassword : wifiPasswords) {
            if (wifiPassword.ssid.equals(pass.ssid)) {
                wifiPasswords.remove(wifiPassword);
            }
        }
        wifiPasswords.add(pass);
        WifiPasswordsSaver.saveWifiPasswords(context, wifiPasswords);
    }


    // filter strings
    private boolean isItemContainsString(String item, String[] str) {
        if (item == null) {
            return false;
        }
        if (str.length <= 0)
            return false;
        for (int i = 0; i < str.length; i++) {
            if (item.startsWith(str[i]))
                return true;
        }
        return false;
    }

    // refresh list
    public void refreshList() {
        initWifiSSIDList();
        wifiAdapter.notifyDataSetChanged();
    }

    // initialization FPV's SSIDList
    private void initWifiSSIDList() {
        List<ScanResult> list = bwm.getWifiList();
        if (list == null)
            return;
        wifiResultList.clear();
        String[] str = getResources().getStringArray(R.array.bind_wifi_camera_contents_strings);
        if (TextUtils.isEmpty(connectedSSID)) {
            for (int i = 0; i < list.size(); i++) {
                if (!TextUtils.isEmpty(list.get(i).SSID)) {
//                    if(showCamera&&isItemContainsString(list.get(i).SSID, str)){
//                        wifiResultList.add(list.get(i));
//                    }else if(!showCamera&&!isItemContainsString(list.get(i).SSID, str)){
//                        wifiResultList.add(list.get(i));
//                    }
                    wifiResultList.add(list.get(i));
                }
            }
        } else {
            connectedWifiTV.setText(connectedSSID);
            statusTV.setText(R.string.connected);
            for (int i = 0; i < list.size(); i++) {
                if (!connectedSSID.equals(list.get(i).SSID) && !TextUtils.isEmpty(list.get(i).SSID)) {
//                    if(showCamera&&isItemContainsString(list.get(i).SSID, str)){
//                        wifiResultList.add(list.get(i));
//                    }else if(!showCamera&&!isItemContainsString(list.get(i).SSID, str)){
//                        wifiResultList.add(list.get(i));
//                    }
                    wifiResultList.add(list.get(i));
                }
            }
        }
        wifiAdapter.notifyDataSetChanged();
    }


    private void initWifi() {
        connecting = false;

        bwm = BindWifiManage.getBindWifiManage();
        wifiManager = bwm.getWifiManager();
        if (!bwm.getWifiStatus()) {
            bwm.openWifi();
        } else if (!"0x".endsWith(bwm.getWifiInfoObject().getSSID())) {
            connectedSSID = bwm.getConnectedSSID().substring(1, bwm.getConnectedSSID().length() - 1);
        }
        scanWifi();
        // refreshList();
    }

    private void scanWifi() {
        wifiResultList.clear();
        wifiAdapter.notifyDataSetChanged();
        bwm.startScan();
    }

    public void connectWifi(final String SSID, final String password, final int type) {
        connecting = true;
        getActivity().runOnUiThread(new Thread(new Runnable() {
            @Override
            public void run() {
                connectedWifiTV.setText("");
                statusTV.setText(R.string.not_connected);
            }
        }));
        WifiHelper.connectWifi(wifiManager, SSID, password, type);
    }

    // login dialog of WIFI
    private void showPasswordDialog() {
        DialogHelper.showLoginWifiDialog(GlobalParams.fragmentManager, currentSelectedWifi.SSID, new LoginWifiDialog.OnConfirmListener() {
            @Override
            public void onConfirm(BaseDialogFragment dialogFragment, String password) {
                dismissKeyBoard();
                dialogFragment.dismiss();
                showLoginProgressDialog();
                int type;
                if (currentSelectedWifi.capabilities.toLowerCase().indexOf("wep") != -1) {
                    type = WifiHelper.WifiCipherType.WIFICIPHER_WEP;
                } else if (currentSelectedWifi.capabilities.toLowerCase().indexOf("wpa") != -1) {
                    type = WifiHelper.WifiCipherType.WIFICIPHER_WPA;
                } else {
                    type = WifiHelper.WifiCipherType.WIFICIPHER_NOPASS;
                }
                passwords.put(currentSelectedWifi.SSID, new WifiPasswordsSaver.WifiPassword(currentSelectedWifi.SSID, password, type));
//                GlobalParams.needReconnectCamera=true;
                connectWifi(currentSelectedWifi.SSID, password, type);
            }
        }, new BaseDialogFragment.OnCancelListener() {
            @Override
            public void onCancel(BaseDialogFragment dialogFragment) {
                dismissKeyBoard();
            }
        });
    }

    private void showLoginProgressDialog() {
        if (loginProgressDialog == null) {
            loginProgressDialog = new ProgressDialog();
            loginProgressDialog.setCancelable(true);
            loginProgressDialog.setMessage(getString(R.string.connecting));
            loginProgressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
                @Override
                public void onCancel(DialogInterface dialog) {
                    wifiManager.disconnect();
                    connecting = false;
                    connectedSSID = "";
                }
            });
        }
        loginProgressDialog.show(getActivity().getFragmentManager(), "LoginProgressDialog");
    }

    public void dismissKeyBoard() {
        InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, InputMethodManager.HIDE_NOT_ALWAYS);
    }

    private class WifiArrayAdapter extends BaseAdapter {
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            TextView tv;
            if (convertView == null) {
                tv = new TextView(context);
                tv.setTextSize(22);
                tv.setTextColor(Color.parseColor("#FFFFFF"));
                tv.setPadding(10, 15, 10, 15);
            } else {
                tv = (TextView) convertView;
            }
            ScanResult item = wifiResultList.get(position);
            tv.setText(String.valueOf(item.SSID));
            return tv;
        }

        @Override
        public int getCount() {
            return wifiResultList.size();
        }

        @Override
        public Object getItem(int position) {
            return wifiResultList.get(position);
        }

        @Override
        public long getItemId(int position) {
            return 0;
        }

    }

    // receiver WiFi's broadcast message
    private BroadcastReceiver receiverWifi = new BroadcastReceiver() {
        private SupplicantState mPreviousState = null;

        @Override
        public void onReceive(Context context, Intent intent) {
            if (wifiManager.isWifiEnabled()) {
                String action = intent.getAction();
                if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
                    refreshList();
                } else if (action.equals(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION)) {
                    if (connecting) {
                        SupplicantState ss = intent.getParcelableExtra(WifiManager.EXTRA_NEW_STATE);
                        int err_state = intent.getIntExtra(WifiManager.EXTRA_SUPPLICANT_ERROR, -1);
                        if (connecting && err_state == WifiManager.ERROR_AUTHENTICATING) {
                            mPreviousState = null;
                            connectedSSID = "";
                            Toast.makeText(context, R.string.password_error, Toast.LENGTH_SHORT).show();
                            connecting = false;
                            if (loginProgressDialog != null) {
                                loginProgressDialog.dismiss();
                            }
                            return;
                        }
                        if (mPreviousState != null) {
                            if (connecting && mPreviousState.equals(SupplicantState.FOUR_WAY_HANDSHAKE)
                                    && ss.equals(SupplicantState.DISCONNECTED)) {
                                // failed
                                mPreviousState = null;
                                connectedSSID = "";
                                Toast.makeText(context, R.string.connect_fail, Toast.LENGTH_SHORT).show();
                                connecting = false;
                                if (loginProgressDialog != null) {
                                    loginProgressDialog.dismiss();
                                }
                                return;
                            }
                        }

                        mPreviousState = ss;

                        if (mPreviousState.equals(SupplicantState.COMPLETED)) {
                            mPreviousState = null;
                        }
                    }
                } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
                    NetworkInfo net_info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
                    NetworkInfo.State state = net_info.getState();
                    if (NetworkInfo.State.CONNECTED == state) {
                        if (connecting) {
                            connecting = false;
                            Toast.makeText(context, R.string.connect_successs, Toast.LENGTH_SHORT).show();
                            if (loginProgressDialog != null) {
                                loginProgressDialog.dismiss();
                            }
                            refreshList();
                            wifiLV.setSelection(0);
                            if (currentSelectedWifi != null) {
                                connectedSSID = currentSelectedWifi.SSID;
                                connectedWifiTV.setText(connectedSSID);
                                statusTV.setText(R.string.connected);
                                if (passwords.containsKey(connectedSSID) && passwords.get(connectedSSID) != null) {
                                    try {
                                        saveWifiPassword(passwords.get(connectedSSID));
                                    } catch (Exception e) {
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    };
}
